package com.siro.auth.controller;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.siro.auth.base.common.domain.PageRequest;
import com.siro.auth.base.common.domain.Result;
import com.siro.auth.base.common.model.LoginResult;
import com.siro.auth.base.constant.CacheConstants;
import com.siro.auth.base.constant.Constants;
import com.siro.auth.base.constant.ResultCode;
import com.siro.auth.base.exception.ServiceException;
import com.siro.auth.entity.SysUser;
import com.siro.auth.entity.dto.UserRoleDto;
import com.siro.auth.service.ISysRoleService;
import com.siro.auth.service.ISysUserService;
import com.siro.auth.utils.JwtUtils;
import com.siro.auth.utils.RedisCache;
import com.siro.auth.utils.SecurityUtils;
import com.siro.auth.utils.excel.ExcelColumnProperty;
import com.siro.auth.utils.excel.ExportDataEntity;
import com.siro.auth.utils.excel.ExportExcel;
import io.jsonwebtoken.Jwts;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author starsea
 * @date 2022-07-13 10:57
 */
@RestController
@RequestMapping("/system/user")
public class SysUserController {
    @Resource
    private RedisCache redisCache;

    @Resource
    private JwtUtils jwtUtils;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private ISysRoleService sysRoleService;

    /**
     * 分页查询用户列表
     *
     * @param pageRequest
     * @return
     */
    @PostMapping("/page")
    public Result getSysUserPage(@RequestBody PageRequest<SysUser> pageRequest) {
        IPage<SysUser> page = sysUserService.getSysUserPage(pageRequest.getPage(), pageRequest.getData());
        return Result.ok(page);
    }

    /**
     * 添加用户
     *
     * @param sysUser
     * @return
     */
    //@PreAuthorize("hasAuthority('sys:user:add')")
    @PostMapping("/add")
    public Result add(@RequestBody SysUser sysUser) {
        //查询用户
        SysUser user = sysUserService.findUserByUserName(sysUser.getUserName());
        //判断对象是否为空
        if (user != null) {
            return Result.fail().message("该登录名称已被使用，请重新输入！");
        }
        //密码加密
        sysUser.setPassword(passwordEncoder.encode(sysUser.getPassword()));
        //TODO 设置默认头像
        sysUser.setAvatar("https://guli-file-190513.oss-cn-beijing.aliyuncs.com/avatar/default.jpg");
        //调用保存用户信息的方法
        boolean save = sysUserService.save(sysUser);
        if (save) {
            return Result.ok().message("用户添加成功");
        }
        return Result.fail().message("用户添加失败");
    }

    /**
     * 修改用户
     *
     * @param sysUser
     * @return
     */
    //@PreAuthorize("hasAuthority('sys:user:edit')")
    @PutMapping("/update")
    public Result update(@RequestBody SysUser sysUser) {
        sysUser.setUpdateBy(SecurityUtils.getUsername());
        sysUser.setUpdateTime(new Date());
        //调用修改用户信息的方法
        if (sysUserService.updateById(sysUser)) {
            return Result.ok().message("用户修改成功");
        }
        return Result.fail().message("用户修改失败");
    }

    /**
     * 删除用户
     *
     * @param userId
     * @return
     */
    //@PreAuthorize("hasAuthority('sys:user:delete')")
    @DeleteMapping("/delete/{userId}")
    public Result delete(@PathVariable Long userId) {
        if (userId.equals(SecurityUtils.getUserId())) {
            return Result.fail().message("当前登录用户禁止删除！");
        }
        //调用删除用户信息的方法
        if (sysUserService.deleteById(userId)) {
            return Result.ok().message("用户删除成功");
        }
        return Result.fail().message("用户删除失败");
    }

    /**
     * 根据用户ID查询该用户拥有的角色列表
     * @param userId
     * @return
     */
    @GetMapping("/getRoleByUserId/{userId}")
    public Result getRoleByUserId(@PathVariable Long userId){
        //调用根据用户ID查询该用户拥有的角色ID的方法
        List<Long> roleIds = sysRoleService.findRoleIdByUserId(userId);
        return Result.ok(roleIds);
    }

    /**
     * 分配角色
     * @param userRoleDTO
     * @return
     */
    @PostMapping("/saveUserRole")
    public Result saveUserRole(@RequestBody UserRoleDto userRoleDTO){
        if (sysUserService.saveUserRole(userRoleDTO.getUserId(), userRoleDTO.getRoleIds())) {
            return Result.ok().message("角色分配成功");
        }
        return Result.fail().message("角色分配失败");
    }

    /**
     * 导出用户列表
     *
     * @param sysUser
     * @param response
     * @throws IOException
     */
    @PostMapping("/export")
    public void exportExcel(@RequestBody SysUser sysUser, HttpServletResponse response) throws IOException {
        //获取数据
        List<Map<String,String>> dataList = sysUserService.selectExportDataList(sysUser);
        if (dataList.size() == 0) {
            throw new ServiceException("当前条件下暂无数据可以导出。", ResultCode.NOT_FOUND);
        }
        //获取表格属性
        List<ExcelColumnProperty> columnList = sysUserService.getExportTitle();
        ExportDataEntity dataEntity = new ExportDataEntity();
        dataEntity.setNameMap(columnList);
        String fileType = "1";
        String isAll = "0";
        String fileName = "用户信息表" + DateUtil.now() + ".xlsx";
        ExportExcel excel = new ExportExcel("用户信息表");
        excel.setExportData(dataEntity);
        excel.initializeTitle(isAll,fileType);
        excel.setDataList(dataList).write(response, fileName).dispose();
    }

    /**
     * 刷新token
     *
     * @param request
     * @return
     */
    @PostMapping("/refreshToken")
    public Result refreshToken(HttpServletRequest request) {
        //从header中获取前端提交的token
        String token = request.getHeader(Constants.TOKEN);
        //如果header中没有token，则从参数中获取
        if (ObjectUtils.isEmpty(token)) {
            token = request.getParameter(Constants.TOKEN);
        }
        //从Spring Security上下文获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //获取身份信息
        UserDetails details = (UserDetails) authentication.getPrincipal();
        //重新生成token
        String reToken = "";
        //验证原来的token是否合法
        if (jwtUtils.validateToken(token, details)) {
            //生成新的token
            reToken = jwtUtils.refreshToken(token);
        }
        //获取本次token的到期时间，交给前端做判断
        long expireTime = Jwts.parser().setSigningKey(jwtUtils.getSecret())
                .parseClaimsJws(reToken.replace("jwt_", ""))
                .getBody().getExpiration().getTime();
        //清除原来的token信息
        String oldTokenKey = CacheConstants.LOGIN_TOKEN_KEY + token;
        redisCache.del(oldTokenKey);
        //存储新的token
        String newTokenKey = CacheConstants.LOGIN_TOKEN_KEY + token;
        redisCache.set(newTokenKey, reToken, jwtUtils.getExpireTime() / 1000);
        //创建TokenVo对象
        LoginResult loginResult = new LoginResult(reToken, expireTime);
        //返回数据
        return Result.ok(loginResult).message("token生成成功");
    }
}
